Hospital Activity and Patient Demographics

https://www.opendata.nhs.scot/dataset/inpatient-and-daycase-activity/resource/00c00ecc-b533-426e-a433-42d79bdea5d4

Activity by Board of Treatment, Age and Sex

library(tidyverse)
library(infer)
age_sex <- read_csv("../clean_data/age_and_sex.csv")

Sex

# Number of "stays" (total number of days patients spend in hospital during a continuous inpatient stay)
# Consistently Female > Male by around 50,000 per quarter
age_sex %>% 
  select(year_quarter, sex, stays) %>%
  group_by(year_quarter, sex) %>%
  summarise(stays_count = sum(stays)) %>% 
  ungroup() %>% 
  ggplot(aes(x = year_quarter, y = stays_count, colour = sex, group = sex)) +
  geom_line() +
  geom_point() +
  labs(
    title = "Stays by sex",
    x = "Quarter ending",
    y = "Stay count")
`summarise()` has grouped output by 'year_quarter'. You can override using the `.groups` argument.

# Mean length of stay
# No clear trend...maybe Female > Male on average
age_sex %>% 
  select(year_quarter, sex, average_length_of_stay) %>% 
  group_by(year_quarter, sex) %>% 
  summarise(mean_stay = mean(average_length_of_stay, na.rm = TRUE)) %>% 
  ungroup() %>%
  ggplot(aes(x = year_quarter, y = mean_stay, group = sex, colour = sex)) +
  geom_line() +
  geom_point() +
  labs(
    title = "Mean Length of Stay by Sex",
    x = "Quarter ending",
    y = "Days")
`summarise()` has grouped output by 'year_quarter'. You can override using the `.groups` argument.

Question 1: To what extent are the ‘winter crises’ reported by the media real?

age_sex %>% 
  group_by(winter) %>% 
  summarise(mean_stays = mean(stays, na.rm = TRUE),
            mean_length_of_stay = mean(average_length_of_stay, na.rm = TRUE))

Doesn’t look like a significant difference.

HYPOTHESIS TESTING

h0: the number of stays (both sexes total) is not significantly greater in winter quarters relative to non-winter quarters h1: the number of stays is greater in winter quarters

# Boxplot
age_sex %>% 
  ggplot(aes(x = stays, y = winter, fill = winter)) +
  geom_boxplot()


# Set up null distriburtion
null_dist_winter <- age_sex %>% 
  specify(stays ~ winter) %>% 
  hypothesise(null = "independence") %>% 
  generate(reps = 1000, type = "permute") %>% 
  calculate(stat = "diff in means", order = c(T, F))

# Calculate the observed stat
obs_stat_winter <- age_sex %>% 
  specify(stays ~ winter) %>% 
  calculate(stat = "diff in means", order = c(T, F))
            
# Visualise confidence interval 
null_dist_winter %>% 
  visualise() +
  shade_p_value(obs_stat = obs_stat_winter, direction = "right")


# Find p-value
pvalue_winter <- null_dist_winter %>% 
  get_p_value(obs_stat = obs_stat_winter, direction = "right")
pvalue_winter
NA

With a p-value around 0.12, we fail to reject the null hypothesis. The number of hospital stays is, on average, greater in winter, but not significantly so.

Question 2: How has the Covid-19 pandemic affected provision of acute care in Scotland?

Overall

age_sex %>% 
  group_by(post_covid) %>% 
  summarise(mean_stays = mean(stays, na.rm = TRUE),
            mean_length_of_stay = mean(average_length_of_stay, na.rm = TRUE))

Drop in the number of stays….significant? Increase in length of stay….significant?

Hypthesis Test h0: There is no significant decrease post-covid in the overall number of stays in hospital. h1: There are significantly fewer stays in hospital post-covid.

age_sex %>% 
  ggplot(aes(x = stays, y = post_covid, fill = post_covid)) +
  geom_boxplot()


null_distribution <- age_sex %>%
  specify(response = stays, explanatory = post_covid) %>% 
  hypothesize(null = "independence") %>%
  generate(reps = 100, type = "permute") %>%
  calculate(stat = "diff in means", order = c(TRUE, FALSE))

observed_stat <- age_sex %>% 
  specify(stays ~ post_covid) %>% 
  calculate(stat= "diff in means", order = c(TRUE, FALSE))

observed_stat
Response: stays (numeric)
Explanatory: post_covid (factor)
null_distribution %>% 
  visualise(bins = 30) +
  shade_p_value(obs_stat = observed_stat, direction = "left")


null_distribution %>% 
  get_p_value(obs_stat = observed_stat, direction = "left")
Warning: Please be cautious in reporting a p-value of 0. This result is an approximation based on the number of `reps` chosen in the `generate()` step. See `?get_p_value()` for more information.

Reject null hypothesis. There are significantly fewer stays in hospital post-covid. Why?

Post-covid changes of different sexes

age_sex %>% 
  group_by(sex, post_covid) %>% 
  summarise(mean_stays = mean(stays, na.rm = TRUE),
            mean_length_of_stay = mean(average_length_of_stay, na.rm = TRUE))
`summarise()` has grouped output by 'sex'. You can override using the `.groups` argument.

Post-covid, the number of stays in both groups has decreased by a lot. Has one sex been affected more than the other? Post-covid, the length of stays in both groups has increased by a small amount. Has one sex been affected more than the other?

# Wrangling data set
male_stays <- age_sex %>% 
  filter(sex == "Male") %>% 
  rename(male_stays = stays,
         average_length_of_male_stay = average_length_of_stay) %>% 
  mutate(id = str_c(year_quarter, hb, location, admission_type, age)) %>% 
  select(id, male_stays, average_length_of_male_stay, winter, post_covid)

female_stays <- age_sex %>% 
  filter(sex == "Female") %>% 
  rename(female_stays = stays,
         average_length_of_female_stay = average_length_of_stay) %>% 
  mutate(id = str_c(year_quarter, hb, location, admission_type, age)) %>% 
  select(id, female_stays, average_length_of_female_stay, winter, post_covid)

age_sex_stay_deltas <- full_join(male_stays, female_stays, by = "id") %>%
  mutate(female_stays = case_when(female_stays > 0 ~ female_stays,
                                  .default = 0),
         average_length_of_female_stay =
           case_when(average_length_of_female_stay > 0 ~ average_length_of_female_stay,
                     .default = 0),
         male_stays = case_when(male_stays > 0 ~ male_stays,
                                .default = 0),
         average_length_of_male_stay =
           case_when(average_length_of_male_stay > 0 ~ average_length_of_male_stay,
                     .default = 0)) %>% 
  rename(winter = winter.x,
         post_covid = post_covid.x) %>% 
  mutate(winter = case_when(winter == TRUE ~ TRUE,
                            winter == FALSE ~ FALSE,
                            .default = winter.y)) %>%
  mutate(post_covid = case_when(post_covid == TRUE ~ TRUE,
                                post_covid == FALSE ~ FALSE,
                                .default = post_covid.y)) %>%
  mutate(more_female_stays = female_stays - male_stays,
         females_stay_longer = average_length_of_female_stay - average_length_of_male_stay) %>% 
  select(more_female_stays, females_stay_longer, winter, post_covid)

Number of hospital stays by sex pre/post covid

Hypothesis test: h0: There is no significant change post-covid in the difference between the number of male and female stays in hospital. h1: There is a significant change post-covid in the difference between the number of male and female stays in hospital.

age_sex_stay_deltas %>% 
  ggplot(aes(x = more_female_stays, y = post_covid, fill = post_covid)) +
  geom_boxplot()


null_distribution <- age_sex_stay_deltas %>%
  specify(response = more_female_stays, explanatory = post_covid) %>% 
  hypothesize(null = "independence") %>%
  generate(reps = 1000, type = "permute") %>%
  calculate(stat = "diff in means", order = c(TRUE, FALSE))

observed_stat <- age_sex_stay_deltas %>% 
  specify(more_female_stays ~ post_covid) %>% 
  calculate(stat= "diff in means", order = c(TRUE, FALSE))

observed_stat
Response: more_female_stays (numeric)
Explanatory: post_covid (factor)
null_distribution %>% 
  visualise(bins = 30) +
  shade_p_value(obs_stat = observed_stat, direction = "both")


null_distribution %>% 
  get_p_value(obs_stat = observed_stat, direction = "both")

Reject null hypothesis There is a significant change post-covid in the difference between the number of male and female stays in hospital. Male stays are lower and the gap has narrowed, so men have been affected more negatively.

Length of hospital stays by sex pre/post covid

Hypothesis test 2: h0: There is no significant change post-covid in the difference between the length of stays of men and women staying in hospital. h1: There is a significant change post-covid in the difference between the length of stays of men and women staying in hospital.

age_sex_stay_deltas %>% 
  ggplot(aes(x = females_stay_longer, y = post_covid, fill = post_covid)) +
  geom_boxplot()


null_distribution <- age_sex_stay_deltas %>%
  specify(response = females_stay_longer, explanatory = post_covid) %>% 
  hypothesize(null = "independence") %>%
  generate(reps = 1000, type = "permute") %>%
  calculate(stat = "diff in means", order = c(TRUE, FALSE))

observed_stat <- age_sex_stay_deltas %>% 
  specify(females_stay_longer ~ post_covid) %>% 
  calculate(stat= "diff in means", order = c(TRUE, FALSE))

observed_stat
Response: females_stay_longer (numeric)
Explanatory: post_covid (factor)
null_distribution %>% 
  visualise(bins = 30) +
  shade_p_value(obs_stat = observed_stat, direction = "both")


null_distribution %>% 
  get_p_value(obs_stat = observed_stat, direction = "both")

Fail to reject null hyposthesis There is no significant change post-covid in the difference between the length of stays of men and women staying in hospital.

LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIEhvc3BpdGFsIEFjdGl2aXR5IGFuZCBQYXRpZW50IERlbW9ncmFwaGljcw0KDQpodHRwczovL3d3dy5vcGVuZGF0YS5uaHMuc2NvdC9kYXRhc2V0L2lucGF0aWVudC1hbmQtZGF5Y2FzZS1hY3Rpdml0eS9yZXNvdXJjZS8wMGMwMGVjYy1iNTMzLTQyNmUtYTQzMy00MmQ3OWJkZWE1ZDQNCg0KIyBBY3Rpdml0eSBieSBCb2FyZCBvZiBUcmVhdG1lbnQsIEFnZSBhbmQgU2V4DQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGluZmVyKQ0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQphZ2Vfc2V4IDwtIHJlYWRfY3N2KCIuLi9jbGVhbl9kYXRhL2FnZV9hbmRfc2V4LmNzdiIpDQpgYGANCg0KYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0NCmdsaW1wc2UoYWdlX3NleCkNCg0Kc3RyKGFnZV9zZXgpDQoNCnNraW1yOjpza2ltKGFnZV9zZXgpDQpgYGANCg0KIyBTZXgNCmBgYHtyfQ0KIyBOdW1iZXIgb2YgInN0YXlzIiAodG90YWwgbnVtYmVyIG9mIGRheXMgcGF0aWVudHMgc3BlbmQgaW4gaG9zcGl0YWwgZHVyaW5nIGEgY29udGludW91cyBpbnBhdGllbnQgc3RheSkNCiMgQ29uc2lzdGVudGx5IEZlbWFsZSA+IE1hbGUgYnkgYXJvdW5kIDUwLDAwMCBwZXIgcXVhcnRlcg0KYWdlX3NleCAlPiUgDQogIHNlbGVjdCh5ZWFyX3F1YXJ0ZXIsIHNleCwgc3RheXMpICU+JQ0KICBncm91cF9ieSh5ZWFyX3F1YXJ0ZXIsIHNleCkgJT4lDQogIHN1bW1hcmlzZShzdGF5c19jb3VudCA9IHN1bShzdGF5cykpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0geWVhcl9xdWFydGVyLCB5ID0gc3RheXNfY291bnQsIGNvbG91ciA9IHNleCwgZ3JvdXAgPSBzZXgpKSArDQogIGdlb21fbGluZSgpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJTdGF5cyBieSBzZXgiLA0KICAgIHggPSAiUXVhcnRlciBlbmRpbmciLA0KICAgIHkgPSAiU3RheSBjb3VudCIpDQoNCg0KIyBNZWFuIGxlbmd0aCBvZiBzdGF5DQojIE5vIGNsZWFyIHRyZW5kLi4ubWF5YmUgRmVtYWxlID4gTWFsZSBvbiBhdmVyYWdlDQojIFJhbmdlIGlzIHNtYWxsDQphZ2Vfc2V4ICU+JSANCiAgc2VsZWN0KHllYXJfcXVhcnRlciwgc2V4LCBhdmVyYWdlX2xlbmd0aF9vZl9zdGF5KSAlPiUgDQogIGdyb3VwX2J5KHllYXJfcXVhcnRlciwgc2V4KSAlPiUgDQogIHN1bW1hcmlzZShtZWFuX3N0YXkgPSBtZWFuKGF2ZXJhZ2VfbGVuZ3RoX29mX3N0YXksIG5hLnJtID0gVFJVRSkpICU+JSANCiAgdW5ncm91cCgpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB5ZWFyX3F1YXJ0ZXIsIHkgPSBtZWFuX3N0YXksIGdyb3VwID0gc2V4LCBjb2xvdXIgPSBzZXgpKSArDQogIGdlb21fbGluZSgpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJNZWFuIExlbmd0aCBvZiBTdGF5IGJ5IFNleCIsDQogICAgeCA9ICJRdWFydGVyIGVuZGluZyIsDQogICAgeSA9ICJEYXlzIikNCmBgYA0KDQojIFF1ZXN0aW9uIDE6IFRvIHdoYXQgZXh0ZW50IGFyZSB0aGUg4oCYd2ludGVyIGNyaXNlc+KAmSByZXBvcnRlZCBieSB0aGUgbWVkaWEgcmVhbD8NCg0KYGBge3J9DQphZ2Vfc2V4ICU+JSANCiAgZ3JvdXBfYnkod2ludGVyKSAlPiUgDQogIHN1bW1hcmlzZShtZWFuX3N0YXlzID0gbWVhbihzdGF5cywgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIG1lYW5fbGVuZ3RoX29mX3N0YXkgPSBtZWFuKGF2ZXJhZ2VfbGVuZ3RoX29mX3N0YXksIG5hLnJtID0gVFJVRSkpDQpgYGANCkRvZXNuJ3QgbG9vayBsaWtlIGEgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZS4NCg0KIyMjIEhZUE9USEVTSVMgVEVTVElORw0KDQpoMDogdGhlIG51bWJlciBvZiBzdGF5cyAoYm90aCBzZXhlcyB0b3RhbCkgaXMgbm90IHNpZ25pZmljYW50bHkgZ3JlYXRlciBpbiB3aW50ZXIgcXVhcnRlcnMgcmVsYXRpdmUgdG8gbm9uLXdpbnRlciBxdWFydGVycw0KaDE6IHRoZSBudW1iZXIgb2Ygc3RheXMgaXMgZ3JlYXRlciBpbiB3aW50ZXIgcXVhcnRlcnMNCg0KYGBge3J9DQojIEJveHBsb3QNCmFnZV9zZXggJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBzdGF5cywgeSA9IHdpbnRlciwgZmlsbCA9IHdpbnRlcikpICsNCiAgZ2VvbV9ib3hwbG90KCkNCg0KIyBTZXQgdXAgbnVsbCBkaXN0cmlidXJ0aW9uDQpudWxsX2Rpc3Rfd2ludGVyIDwtIGFnZV9zZXggJT4lIA0KICBzcGVjaWZ5KHN0YXlzIH4gd2ludGVyKSAlPiUgDQogIGh5cG90aGVzaXNlKG51bGwgPSAiaW5kZXBlbmRlbmNlIikgJT4lIA0KICBnZW5lcmF0ZShyZXBzID0gMTAwMCwgdHlwZSA9ICJwZXJtdXRlIikgJT4lIA0KICBjYWxjdWxhdGUoc3RhdCA9ICJkaWZmIGluIG1lYW5zIiwgb3JkZXIgPSBjKFQsIEYpKQ0KDQojIENhbGN1bGF0ZSB0aGUgb2JzZXJ2ZWQgc3RhdA0Kb2JzX3N0YXRfd2ludGVyIDwtIGFnZV9zZXggJT4lIA0KICBzcGVjaWZ5KHN0YXlzIH4gd2ludGVyKSAlPiUgDQogIGNhbGN1bGF0ZShzdGF0ID0gImRpZmYgaW4gbWVhbnMiLCBvcmRlciA9IGMoVCwgRikpDQogICAgICAgICAgICANCiMgVmlzdWFsaXNlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgDQpudWxsX2Rpc3Rfd2ludGVyICU+JSANCiAgdmlzdWFsaXNlKCkgKw0KICBzaGFkZV9wX3ZhbHVlKG9ic19zdGF0ID0gb2JzX3N0YXRfd2ludGVyLCBkaXJlY3Rpb24gPSAicmlnaHQiKQ0KDQojIEZpbmQgcC12YWx1ZQ0KcHZhbHVlX3dpbnRlciA8LSBudWxsX2Rpc3Rfd2ludGVyICU+JSANCiAgZ2V0X3BfdmFsdWUob2JzX3N0YXQgPSBvYnNfc3RhdF93aW50ZXIsIGRpcmVjdGlvbiA9ICJyaWdodCIpDQpwdmFsdWVfd2ludGVyDQoNCmBgYA0KV2l0aCBhIHAtdmFsdWUgYXJvdW5kIDAuMTIsIHdlIGZhaWwgdG8gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMuDQpUaGUgbnVtYmVyIG9mIGhvc3BpdGFsIHN0YXlzIGlzLCBvbiBhdmVyYWdlLCBncmVhdGVyIGluIHdpbnRlciwgYnV0IG5vdCBzaWduaWZpY2FudGx5IHNvLg0KDQoNCiMgUXVlc3Rpb24gMjogSG93IGhhcyB0aGUgQ292aWQtMTkgcGFuZGVtaWMgYWZmZWN0ZWQgcHJvdmlzaW9uIG9mIGFjdXRlIGNhcmUgaW4gU2NvdGxhbmQ/DQotIERlbW9ncmFwaGljOiBXaG8gaXMgbW9zdCBhZmZlY3RlZCBieSB0aGlzIGlzc3VlPyAoV2hvIHNob3VsZCBiZSB0YXJnZXRlZCB3aXRoIGVmZm9ydHM/KQ0KDQojIyBPdmVyYWxsDQpgYGB7cn0NCmFnZV9zZXggJT4lIA0KICBncm91cF9ieShwb3N0X2NvdmlkKSAlPiUgDQogIHN1bW1hcmlzZShtZWFuX3N0YXlzID0gbWVhbihzdGF5cywgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIG1lYW5fbGVuZ3RoX29mX3N0YXkgPSBtZWFuKGF2ZXJhZ2VfbGVuZ3RoX29mX3N0YXksIG5hLnJtID0gVFJVRSkpDQpgYGANCkRyb3AgaW4gdGhlIG51bWJlciBvZiBzdGF5cy4uLi5zaWduaWZpY2FudD8NCkluY3JlYXNlIGluIGxlbmd0aCBvZiBzdGF5Li4uLnNpZ25pZmljYW50Pw0KDQoqSHlwdGhlc2lzIFRlc3QqDQpoMDogVGhlcmUgaXMgbm8gc2lnbmlmaWNhbnQgZGVjcmVhc2UgcG9zdC1jb3ZpZCBpbiB0aGUgb3ZlcmFsbCBudW1iZXIgb2Ygc3RheXMgaW4gaG9zcGl0YWwuDQpoMTogVGhlcmUgYXJlIHNpZ25pZmljYW50bHkgZmV3ZXIgc3RheXMgaW4gaG9zcGl0YWwgcG9zdC1jb3ZpZC4NCmBgYHtyfQ0KYWdlX3NleCAlPiUgDQogIGdncGxvdChhZXMoeCA9IHN0YXlzLCB5ID0gcG9zdF9jb3ZpZCwgZmlsbCA9IHBvc3RfY292aWQpKSArDQogIGdlb21fYm94cGxvdCgpDQoNCm51bGxfZGlzdHJpYnV0aW9uIDwtIGFnZV9zZXggJT4lDQogIHNwZWNpZnkocmVzcG9uc2UgPSBzdGF5cywgZXhwbGFuYXRvcnkgPSBwb3N0X2NvdmlkKSAlPiUgDQogIGh5cG90aGVzaXplKG51bGwgPSAiaW5kZXBlbmRlbmNlIikgJT4lDQogIGdlbmVyYXRlKHJlcHMgPSAxMDAsIHR5cGUgPSAicGVybXV0ZSIpICU+JQ0KICBjYWxjdWxhdGUoc3RhdCA9ICJkaWZmIGluIG1lYW5zIiwgb3JkZXIgPSBjKFRSVUUsIEZBTFNFKSkNCg0Kb2JzZXJ2ZWRfc3RhdCA8LSBhZ2Vfc2V4ICU+JSANCiAgc3BlY2lmeShzdGF5cyB+IHBvc3RfY292aWQpICU+JSANCiAgY2FsY3VsYXRlKHN0YXQ9ICJkaWZmIGluIG1lYW5zIiwgb3JkZXIgPSBjKFRSVUUsIEZBTFNFKSkNCg0Kb2JzZXJ2ZWRfc3RhdA0KDQpudWxsX2Rpc3RyaWJ1dGlvbiAlPiUgDQogIHZpc3VhbGlzZShiaW5zID0gMzApICsNCiAgc2hhZGVfcF92YWx1ZShvYnNfc3RhdCA9IG9ic2VydmVkX3N0YXQsIGRpcmVjdGlvbiA9ICJsZWZ0IikNCg0KbnVsbF9kaXN0cmlidXRpb24gJT4lIA0KICBnZXRfcF92YWx1ZShvYnNfc3RhdCA9IG9ic2VydmVkX3N0YXQsIGRpcmVjdGlvbiA9ICJsZWZ0IikNCmBgYA0KKlJlamVjdCBudWxsIGh5cG90aGVzaXMuKg0KKlRoZXJlIGFyZSBzaWduaWZpY2FudGx5IGZld2VyIHN0YXlzIGluIGhvc3BpdGFsIHBvc3QtY292aWQuKiAgV2h5Pw0KDQoNCiMjIFBvc3QtY292aWQgY2hhbmdlcyBvZiBkaWZmZXJlbnQgc2V4ZXMNCmBgYHtyfQ0KYWdlX3NleCAlPiUgDQogIGdyb3VwX2J5KHNleCwgcG9zdF9jb3ZpZCkgJT4lIA0KICBzdW1tYXJpc2UobWVhbl9zdGF5cyA9IG1lYW4oc3RheXMsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICBtZWFuX2xlbmd0aF9vZl9zdGF5ID0gbWVhbihhdmVyYWdlX2xlbmd0aF9vZl9zdGF5LCBuYS5ybSA9IFRSVUUpKQ0KYGBgDQpQb3N0LWNvdmlkLCB0aGUgbnVtYmVyIG9mIHN0YXlzIGluIGJvdGggZ3JvdXBzIGhhcyBkZWNyZWFzZWQgYnkgYSBsb3QuIEhhcyBvbmUgc2V4IGJlZW4gYWZmZWN0ZWQgbW9yZSB0aGFuIHRoZSBvdGhlcj8NClBvc3QtY292aWQsIHRoZSBsZW5ndGggb2Ygc3RheXMgaW4gYm90aCBncm91cHMgaGFzIGluY3JlYXNlZCBieSBhIHNtYWxsIGFtb3VudC4gIEhhcyBvbmUgc2V4IGJlZW4gYWZmZWN0ZWQgbW9yZSB0aGFuIHRoZSBvdGhlcj8NCg0KYGBge3J9DQojIFdyYW5nbGluZyBkYXRhIHNldA0KbWFsZV9zdGF5cyA8LSBhZ2Vfc2V4ICU+JSANCiAgZmlsdGVyKHNleCA9PSAiTWFsZSIpICU+JSANCiAgcmVuYW1lKG1hbGVfc3RheXMgPSBzdGF5cywNCiAgICAgICAgIGF2ZXJhZ2VfbGVuZ3RoX29mX21hbGVfc3RheSA9IGF2ZXJhZ2VfbGVuZ3RoX29mX3N0YXkpICU+JSANCiAgbXV0YXRlKGlkID0gc3RyX2MoeWVhcl9xdWFydGVyLCBoYiwgbG9jYXRpb24sIGFkbWlzc2lvbl90eXBlLCBhZ2UpKSAlPiUgDQogIHNlbGVjdChpZCwgbWFsZV9zdGF5cywgYXZlcmFnZV9sZW5ndGhfb2ZfbWFsZV9zdGF5LCB3aW50ZXIsIHBvc3RfY292aWQpDQoNCmZlbWFsZV9zdGF5cyA8LSBhZ2Vfc2V4ICU+JSANCiAgZmlsdGVyKHNleCA9PSAiRmVtYWxlIikgJT4lIA0KICByZW5hbWUoZmVtYWxlX3N0YXlzID0gc3RheXMsDQogICAgICAgICBhdmVyYWdlX2xlbmd0aF9vZl9mZW1hbGVfc3RheSA9IGF2ZXJhZ2VfbGVuZ3RoX29mX3N0YXkpICU+JSANCiAgbXV0YXRlKGlkID0gc3RyX2MoeWVhcl9xdWFydGVyLCBoYiwgbG9jYXRpb24sIGFkbWlzc2lvbl90eXBlLCBhZ2UpKSAlPiUgDQogIHNlbGVjdChpZCwgZmVtYWxlX3N0YXlzLCBhdmVyYWdlX2xlbmd0aF9vZl9mZW1hbGVfc3RheSwgd2ludGVyLCBwb3N0X2NvdmlkKQ0KDQphZ2Vfc2V4X3N0YXlfZGVsdGFzIDwtIGZ1bGxfam9pbihtYWxlX3N0YXlzLCBmZW1hbGVfc3RheXMsIGJ5ID0gImlkIikgJT4lDQogIG11dGF0ZShmZW1hbGVfc3RheXMgPSBjYXNlX3doZW4oZmVtYWxlX3N0YXlzID4gMCB+IGZlbWFsZV9zdGF5cywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IDApLA0KICAgICAgICAgYXZlcmFnZV9sZW5ndGhfb2ZfZmVtYWxlX3N0YXkgPQ0KICAgICAgICAgICBjYXNlX3doZW4oYXZlcmFnZV9sZW5ndGhfb2ZfZmVtYWxlX3N0YXkgPiAwIH4gYXZlcmFnZV9sZW5ndGhfb2ZfZmVtYWxlX3N0YXksDQogICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IDApLA0KICAgICAgICAgbWFsZV9zdGF5cyA9IGNhc2Vfd2hlbihtYWxlX3N0YXlzID4gMCB+IG1hbGVfc3RheXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gMCksDQogICAgICAgICBhdmVyYWdlX2xlbmd0aF9vZl9tYWxlX3N0YXkgPQ0KICAgICAgICAgICBjYXNlX3doZW4oYXZlcmFnZV9sZW5ndGhfb2ZfbWFsZV9zdGF5ID4gMCB+IGF2ZXJhZ2VfbGVuZ3RoX29mX21hbGVfc3RheSwNCiAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gMCkpICU+JSANCiAgcmVuYW1lKHdpbnRlciA9IHdpbnRlci54LA0KICAgICAgICAgcG9zdF9jb3ZpZCA9IHBvc3RfY292aWQueCkgJT4lIA0KICBtdXRhdGUod2ludGVyID0gY2FzZV93aGVuKHdpbnRlciA9PSBUUlVFIH4gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aW50ZXIgPT0gRkFMU0UgfiBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IHdpbnRlci55KSkgJT4lDQogIG11dGF0ZShwb3N0X2NvdmlkID0gY2FzZV93aGVuKHBvc3RfY292aWQgPT0gVFJVRSB+IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc3RfY292aWQgPT0gRkFMU0UgfiBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSBwb3N0X2NvdmlkLnkpKSAlPiUNCiAgbXV0YXRlKG1vcmVfZmVtYWxlX3N0YXlzID0gZmVtYWxlX3N0YXlzIC0gbWFsZV9zdGF5cywNCiAgICAgICAgIGZlbWFsZXNfc3RheV9sb25nZXIgPSBhdmVyYWdlX2xlbmd0aF9vZl9mZW1hbGVfc3RheSAtIGF2ZXJhZ2VfbGVuZ3RoX29mX21hbGVfc3RheSkgJT4lIA0KICBzZWxlY3QobW9yZV9mZW1hbGVfc3RheXMsIGZlbWFsZXNfc3RheV9sb25nZXIsIHdpbnRlciwgcG9zdF9jb3ZpZCkNCmBgYA0KDQoNCiMjIyBOdW1iZXIgb2YgaG9zcGl0YWwgc3RheXMgYnkgc2V4IHByZS9wb3N0IGNvdmlkDQpIeXBvdGhlc2lzIHRlc3Q6DQpoMDogVGhlcmUgaXMgbm8gc2lnbmlmaWNhbnQgY2hhbmdlIHBvc3QtY292aWQgaW4gdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbnVtYmVyIG9mIG1hbGUgYW5kIGZlbWFsZSBzdGF5cyBpbiBob3NwaXRhbC4NCmgxOiBUaGVyZSBpcyBhIHNpZ25pZmljYW50IGNoYW5nZSBwb3N0LWNvdmlkIGluIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIG51bWJlciBvZiBtYWxlIGFuZCBmZW1hbGUgc3RheXMgaW4gaG9zcGl0YWwuDQpgYGB7cn0NCmFnZV9zZXhfc3RheV9kZWx0YXMgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBtb3JlX2ZlbWFsZV9zdGF5cywgeSA9IHBvc3RfY292aWQsIGZpbGwgPSBwb3N0X2NvdmlkKSkgKw0KICBnZW9tX2JveHBsb3QoKQ0KDQpudWxsX2Rpc3RyaWJ1dGlvbiA8LSBhZ2Vfc2V4X3N0YXlfZGVsdGFzICU+JQ0KICBzcGVjaWZ5KHJlc3BvbnNlID0gbW9yZV9mZW1hbGVfc3RheXMsIGV4cGxhbmF0b3J5ID0gcG9zdF9jb3ZpZCkgJT4lIA0KICBoeXBvdGhlc2l6ZShudWxsID0gImluZGVwZW5kZW5jZSIpICU+JQ0KICBnZW5lcmF0ZShyZXBzID0gMTAwMCwgdHlwZSA9ICJwZXJtdXRlIikgJT4lDQogIGNhbGN1bGF0ZShzdGF0ID0gImRpZmYgaW4gbWVhbnMiLCBvcmRlciA9IGMoVFJVRSwgRkFMU0UpKQ0KDQpvYnNlcnZlZF9zdGF0IDwtIGFnZV9zZXhfc3RheV9kZWx0YXMgJT4lIA0KICBzcGVjaWZ5KG1vcmVfZmVtYWxlX3N0YXlzIH4gcG9zdF9jb3ZpZCkgJT4lIA0KICBjYWxjdWxhdGUoc3RhdD0gImRpZmYgaW4gbWVhbnMiLCBvcmRlciA9IGMoVFJVRSwgRkFMU0UpKQ0KDQpvYnNlcnZlZF9zdGF0DQoNCm51bGxfZGlzdHJpYnV0aW9uICU+JSANCiAgdmlzdWFsaXNlKGJpbnMgPSAzMCkgKw0KICBzaGFkZV9wX3ZhbHVlKG9ic19zdGF0ID0gb2JzZXJ2ZWRfc3RhdCwgZGlyZWN0aW9uID0gImJvdGgiKQ0KDQpudWxsX2Rpc3RyaWJ1dGlvbiAlPiUgDQogIGdldF9wX3ZhbHVlKG9ic19zdGF0ID0gb2JzZXJ2ZWRfc3RhdCwgZGlyZWN0aW9uID0gImJvdGgiKQ0KYGBgDQoqUmVqZWN0IG51bGwgaHlwb3RoZXNpcyoNCipUaGVyZSBpcyBhIHNpZ25pZmljYW50IGNoYW5nZSBwb3N0LWNvdmlkIGluIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIG51bWJlciBvZiBtYWxlIGFuZCBmZW1hbGUgc3RheXMgaW4gaG9zcGl0YWwuKg0KKk1hbGUgc3RheXMgYXJlIGxvd2VyIGFuZCB0aGUgZ2FwIGhhcyBuYXJyb3dlZCwgc28gbWVuIGhhdmUgYmVlbiBhZmZlY3RlZCBtb3JlIG5lZ2F0aXZlbHkuKg0KDQojIyMgTGVuZ3RoIG9mIGhvc3BpdGFsIHN0YXlzIGJ5IHNleCBwcmUvcG9zdCBjb3ZpZA0KSHlwb3RoZXNpcyB0ZXN0IDI6DQpoMDogVGhlcmUgaXMgbm8gc2lnbmlmaWNhbnQgY2hhbmdlIHBvc3QtY292aWQgaW4gdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbGVuZ3RoIG9mIHN0YXlzIG9mIG1lbiBhbmQgd29tZW4gc3RheWluZyBpbiBob3NwaXRhbC4NCmgxOiBUaGVyZSBpcyBhIHNpZ25pZmljYW50IGNoYW5nZSBwb3N0LWNvdmlkIGluIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGxlbmd0aCBvZiBzdGF5cyBvZiBtZW4gYW5kIHdvbWVuIHN0YXlpbmcgaW4gaG9zcGl0YWwuDQoNCmBgYHtyfQ0KYWdlX3NleF9zdGF5X2RlbHRhcyAlPiUgDQogIGdncGxvdChhZXMoeCA9IGZlbWFsZXNfc3RheV9sb25nZXIsIHkgPSBwb3N0X2NvdmlkLCBmaWxsID0gcG9zdF9jb3ZpZCkpICsNCiAgZ2VvbV9ib3hwbG90KCkNCg0KbnVsbF9kaXN0cmlidXRpb24gPC0gYWdlX3NleF9zdGF5X2RlbHRhcyAlPiUNCiAgc3BlY2lmeShyZXNwb25zZSA9IGZlbWFsZXNfc3RheV9sb25nZXIsIGV4cGxhbmF0b3J5ID0gcG9zdF9jb3ZpZCkgJT4lIA0KICBoeXBvdGhlc2l6ZShudWxsID0gImluZGVwZW5kZW5jZSIpICU+JQ0KICBnZW5lcmF0ZShyZXBzID0gMTAwMCwgdHlwZSA9ICJwZXJtdXRlIikgJT4lDQogIGNhbGN1bGF0ZShzdGF0ID0gImRpZmYgaW4gbWVhbnMiLCBvcmRlciA9IGMoVFJVRSwgRkFMU0UpKQ0KDQpvYnNlcnZlZF9zdGF0IDwtIGFnZV9zZXhfc3RheV9kZWx0YXMgJT4lIA0KICBzcGVjaWZ5KGZlbWFsZXNfc3RheV9sb25nZXIgfiBwb3N0X2NvdmlkKSAlPiUgDQogIGNhbGN1bGF0ZShzdGF0PSAiZGlmZiBpbiBtZWFucyIsIG9yZGVyID0gYyhUUlVFLCBGQUxTRSkpDQoNCm9ic2VydmVkX3N0YXQNCg0KbnVsbF9kaXN0cmlidXRpb24gJT4lIA0KICB2aXN1YWxpc2UoYmlucyA9IDMwKSArDQogIHNoYWRlX3BfdmFsdWUob2JzX3N0YXQgPSBvYnNlcnZlZF9zdGF0LCBkaXJlY3Rpb24gPSAiYm90aCIpDQoNCm51bGxfZGlzdHJpYnV0aW9uICU+JSANCiAgZ2V0X3BfdmFsdWUob2JzX3N0YXQgPSBvYnNlcnZlZF9zdGF0LCBkaXJlY3Rpb24gPSAiYm90aCIpDQpgYGANCipGYWlsIHRvIHJlamVjdCBudWxsIGh5cG9zdGhlc2lzKg0KKlRoZXJlIGlzIG5vIHNpZ25pZmljYW50IGNoYW5nZSBwb3N0LWNvdmlkIGluIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGxlbmd0aCBvZiBzdGF5cyBvZiBtZW4gYW5kIHdvbWVuIHN0YXlpbmcgaW4gaG9zcGl0YWwuKg0KDQoNCg0KDQoNCg0K